﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;

namespace CreditAgricole.Framework
{
    public static class QueryBuilder
    {

        public static SPQuery GetSelectedItems(string type, string property, string value, IDictionary<string, string> filter, string orderBy, bool Ascending)
        {
            SPQuery query = new SPQuery();
            StringBuilder queryString = new StringBuilder(String.Empty);
            StringBuilder filterQueryString = new StringBuilder(String.Empty);
            queryString.Append(@"<Where>");
            if (filter == null)
            {
                queryString.Append(@"   <Eq>");
                queryString.Append(@"       <FieldRef Name='" + property + @"' />");
                queryString.Append(@"       <Value Type='" + type + "'>" + value + "</Value>");
                queryString.Append(@"   </Eq>");
            }
            else
            {
                filterQueryString = AddCriteriaToQuery(filter);
                if (string.IsNullOrEmpty(property) && string.IsNullOrEmpty(value))
                {
                    if (filter.Count > 1)
                    {
                        queryString.Append(@"   <And>");
                        queryString.Append(filterQueryString);
                        queryString.Append(@"   </And>");
                    }
                    else
                    {
                        queryString.Append(filterQueryString);
                    }
                }
                else
                {
                    queryString.Append(@"   <And>");
                    queryString.Append(@"   <Eq>");
                    queryString.Append(@"       <FieldRef Name='" + property + @"' />");
                    queryString.Append(@"       <Value Type='" + type + "'>" + value + "</Value>");
                    queryString.Append(@"   </Eq>");
                    queryString.Append(filterQueryString);
                    queryString.Append(@"   </And>");
                }
            }
            queryString.Append(@"</Where>");
            if (!string.IsNullOrEmpty(orderBy))
            {
                queryString.Append(@"<OrderBy>");
                queryString.Append(@"<FieldRef Ascending='" + (Ascending ? "TRUE" : "FALSE") + @"' Name='" + orderBy + @"' />");
                queryString.Append(@"</OrderBy>");
            }
            query.Query = queryString.ToString();
            return query;
        }

        public static SPQuery GetSelectedItemsOrderBy(string orderBy, bool Ascending)
        {
            SPQuery query = new SPQuery();
            StringBuilder queryString = new StringBuilder(String.Empty);
            queryString.Append(@"<OrderBy>");
            queryString.Append(@"<FieldRef Ascending='" + (Ascending ? "TRUE" : "FALSE") + @"' Name='" + orderBy + @"' />");
            queryString.Append(@"</OrderBy>");
            query.Query = queryString.ToString();
            return query;
        }

        private static StringBuilder AddCriteriaToQuery(IDictionary<string, string> filter)
        {
            return AddCriteriaToQuery(filter, Constants.CamlQueryOperator.Equal);
        }

        public static SPQuery GetQueryWithFileNames(string type, string property, string value, List<string> fileNameList)
        {
            SPQuery query = new SPQuery();
            StringBuilder queryString = new StringBuilder(String.Empty);
            queryString.Append(@"<Where>");
            if (fileNameList != null)
            {
                if (fileNameList.Count <= 2)
                {
                    queryString.Append(@"<Or>");
                    foreach (string fileName in fileNameList)
                    {
                        queryString.Append(@"   <And>");
                        queryString.Append(@"       <Eq>");
                        queryString.Append(@"           <FieldRef Name='" + property + @"' />");
                        queryString.Append(@"           <Value Type='" + type + "'>" + value + @"</Value>");
                        queryString.Append(@"       </Eq>");
                        queryString.Append(@"       <Eq>");
                        queryString.Append(@"           <FieldRef Name='LinkFilename' />");
                        queryString.Append(@"           <Value Type='Text'>" + fileName + @"</Value>");
                        queryString.Append(@"       </Eq>");
                        queryString.Append(@"   </And>");
                    }
                    queryString.Append(@"</Or>");
                }
                else
                {
                    StringBuilder baseQueryString = new StringBuilder();
                    
                    #region Add 2 first file names in conditions
                    
                    baseQueryString.Append(@"<Or>");
                    baseQueryString.Append(@"   <And>");
                    baseQueryString.Append(@"       <Eq>");
                    baseQueryString.Append(@"           <FieldRef Name='" + property + @"' />");
                    baseQueryString.Append(@"           <Value Type='" + type + "'>" + value + @"</Value>");
                    baseQueryString.Append(@"       </Eq>");
                    baseQueryString.Append(@"       <Eq>");
                    baseQueryString.Append(@"           <FieldRef Name='LinkFilename' />");
                    baseQueryString.Append(@"           <Value Type='Text'>" + fileNameList[0] + @"</Value>");
                    baseQueryString.Append(@"       </Eq>");
                    baseQueryString.Append(@"   </And>");
                    baseQueryString.Append(@"   <And>");
                    baseQueryString.Append(@"       <Eq>");
                    baseQueryString.Append(@"           <FieldRef Name='" + property + @"' />");
                    baseQueryString.Append(@"           <Value Type='" + type + "'>" + value + @"</Value>");
                    baseQueryString.Append(@"       </Eq>");
                    baseQueryString.Append(@"       <Eq>");
                    baseQueryString.Append(@"           <FieldRef Name='LinkFilename' />");
                    baseQueryString.Append(@"           <Value Type='Text'>" + fileNameList[1] + @"</Value>");
                    baseQueryString.Append(@"       </Eq>");
                    baseQueryString.Append(@"   </And>");
                    baseQueryString.Append(@"</Or>");
                    
                    #endregion

                    StringBuilder additionnalQueryString = new StringBuilder();
                    
                    #region Add rest of file names in conditions
                    for (int i = 2; i < fileNameList.Count; i++)
                    {
                        additionnalQueryString.Append(@"<Or>");
                        additionnalQueryString.Append(@"   <And>");
                        additionnalQueryString.Append(@"       <Eq>");
                        additionnalQueryString.Append(@"           <FieldRef Name='" + property + @"' />");
                        additionnalQueryString.Append(@"           <Value Type='" + type + "'>" + value + @"</Value>");
                        additionnalQueryString.Append(@"       </Eq>");
                        additionnalQueryString.Append(@"       <Eq>");
                        additionnalQueryString.Append(@"           <FieldRef Name='LinkFilename' />");
                        additionnalQueryString.Append(@"           <Value Type='Text'>" + fileNameList[i] + @"</Value>");
                        additionnalQueryString.Append(@"       </Eq>");
                        additionnalQueryString.Append(@"   </And>");
                        additionnalQueryString.Append(baseQueryString);
                        additionnalQueryString.Append(@"</Or>");
                        if (i < fileNameList.Count)
                        {
                            baseQueryString = new StringBuilder(additionnalQueryString.ToString());
                            additionnalQueryString.Length = 0;
                        }
                    }
                    queryString.Append(baseQueryString);

                    #endregion
                }
            }
            queryString.Append(@"</Where>");
            query.Query = queryString.ToString();
            return query;
        }

        public static SPQuery GetSelectedItems(string property1, string value1, Constants.CamlQueryOperator queryOp1, string property2, string value2, Constants.CamlQueryOperator queryOp2)
        {
            SPQuery query = new SPQuery();
            StringBuilder queryString = new StringBuilder(String.Empty);
            queryString.Append(@"<Where>");
            queryString.Append(@"   <And>");
            switch (queryOp1)
            {
                case Constants.CamlQueryOperator.Equal:
                    {
                        queryString.Append(@"   <Eq>");
                        queryString.Append(@"       <FieldRef Name='" + property1 + @"' />");
                        queryString.Append(@"       <Value Type='Text'>" + value1 + "</Value>");
                        queryString.Append(@"   </Eq>");
                        break;
                    }
                case Constants.CamlQueryOperator.NotEqual:
                    {
                        queryString.Append(@"   <Neq>");
                        queryString.Append(@"       <FieldRef Name='" + property1 + @"' />");
                        queryString.Append(@"       <Value Type='Text'>" + value1 + "</Value>");
                        queryString.Append(@"   </Neq>");
                        break;
                    }
            }
            switch (queryOp2)
            {
                case Constants.CamlQueryOperator.Equal:
                    {
                        queryString.Append(@"   <Eq>");
                        queryString.Append(@"       <FieldRef Name='" + property2 + @"' />");
                        queryString.Append(@"       <Value Type='Text'>" + value2 + "</Value>");
                        queryString.Append(@"   </Eq>");
                        break;
                    }
                case Constants.CamlQueryOperator.NotEqual:
                    {
                        queryString.Append(@"   <Neq>");
                        queryString.Append(@"       <FieldRef Name='" + property2 + @"' />");
                        queryString.Append(@"       <Value Type='Text'>" + value2 + "</Value>");
                        queryString.Append(@"   </Neq>");
                        break;
                    }
            }
            queryString.Append(@"   </And>");
            queryString.Append(@"</Where>");
            query.Query = queryString.ToString();
            return query;
        }

        private static StringBuilder AddCriteriaToQuery(IDictionary<string, string> filter, Constants.CamlQueryOperator queryOperator)
        {
            StringBuilder filterQueryString = new StringBuilder();
            switch (queryOperator)
            {
                case Constants.CamlQueryOperator.Equal:
                    {
                        foreach (var condition in filter)
                        {
                            filterQueryString.Append(@"   <Eq>");
                            filterQueryString.Append(@"       <FieldRef Name='" + condition.Key + @"' />");
                            filterQueryString.Append(@"       <Value Type='Text'>" + condition.Value + "</Value>");
                            filterQueryString.Append(@"   </Eq>");
                        }
                        break;
                    }
                case Constants.CamlQueryOperator.NotEqual:
                    {
                        foreach (var condition in filter)
                        {
                            filterQueryString.Append(@"   <Neq>");
                            filterQueryString.Append(@"       <FieldRef Name='" + condition.Key + @"' />");
                            filterQueryString.Append(@"       <Value Type='Text'>" + condition.Value + "</Value>");
                            filterQueryString.Append(@"   </Neq>");
                        }
                        break;
                    }
            }
            return filterQueryString;
        }

        public static SPQuery GetSelectedItemsWithLookup(string type, string property, string value, IDictionary<string, string> filter)
        {
            return GetSelectedItemsWithLookup(type, property, value, Constants.CamlQueryOperator.Equal, filter, Constants.CamlQueryOperator.Equal);
        }
        
        public static SPQuery GetSelectedItemsWithLookup(string type, string property, string value, 
                                                         Constants.CamlQueryOperator queryOperator1,
                                                         IDictionary<string,string> filter, 
                                                         Constants.CamlQueryOperator queryOperator2)
        {
            SPQuery query = new SPQuery();
            StringBuilder queryString = new StringBuilder(String.Empty);
            if (filter != null)
            {
                StringBuilder filterQuery = AddCriteriaToQuery(filter, queryOperator2);
                queryString.Append(@"<Where>");
                queryString.Append(@"   <And>");
                if(queryOperator1 == Constants.CamlQueryOperator.Equal)
                    queryString.Append(@"   <Eq>");
                else
                    queryString.Append(@"   <Neq>");
                queryString.Append(@"       <FieldRef Name='" + property + @"' LookupId='True' />");
                queryString.Append(@"       <Value Type='" + type + "'>" + value + @"</Value>");
                if (queryOperator1 == Constants.CamlQueryOperator.Equal)
                    queryString.Append(@"   </Eq>");
                else
                    queryString.Append(@"   </Neq>");
                queryString.Append(filterQuery.ToString());
                queryString.Append(@"   </And>");
                queryString.Append(@"</Where>");
            }
            else
            {
                queryString.Append(@"<Where>");
                if (queryOperator1 == Constants.CamlQueryOperator.Equal)
                    queryString.Append(@"   <Eq>");
                else
                    queryString.Append(@"   <Neq>");
                queryString.Append(@"       <FieldRef Name='" + property + @"' LookupId='True' />");
                queryString.Append(@"       <Value Type='" + type + "'>" + value + @"</Value>");
                if (queryOperator1 == Constants.CamlQueryOperator.Equal)
                    queryString.Append(@"   </Eq>");
                else
                    queryString.Append(@"   </Neq>");
                queryString.Append(@"</Where>");
            }
            query.Query = queryString.ToString();
            return query;
        }

        public static SPQuery GetSelectedItemsWithLookup(string type, string property, string value)
        {
            return GetSelectedItemsWithLookup(type, property, value, null);
        }

        public static SPQuery GetSelectedItems(string type, string property, string value, IDictionary<string, string> filter, string orderBy)
        {
            return GetSelectedItems(type, property, value, filter, orderBy, true);
        }

        public static SPQuery GetSelectedItems(string type, string property, string value, IDictionary<string, string> filter)
        {
            return GetSelectedItems(type, property, value, filter, string.Empty);
        }

        public static SPQuery GetSelectedItems(IDictionary<string, string> filter, string orderBy, bool Ascending)
        {
            return GetSelectedItems(string.Empty, string.Empty, string.Empty, filter, orderBy, Ascending);
        }

        public static SPQuery GetSelectedItems(IDictionary<string, string> filter, string orderBy)
        {
            return GetSelectedItems(string.Empty, string.Empty, string.Empty, filter, orderBy);
        }

        public static SPQuery GetSelectedItems(IDictionary<string, string> filter)
        {
            return GetSelectedItems(string.Empty, string.Empty, string.Empty, filter, string.Empty);
        }

        public static SPQuery GetSelectedItemsOrderBy(string orderBy)
        {
            return GetSelectedItemsOrderBy(orderBy, true);
        }


    }
}
